import axios from "axios";
import type { AxiosRequestConfig, AxiosResponse } from "axios";
import { StorageEnum, RequestEnum } from "@/enums";
import { getLocalStorage } from "@/utils";

import UtilVar from "../config/UtilVar";
import { error } from "console";
let baseUrl =UtilVar.baseUrl
/**
 * 路由已经跳转，而上一页的请求还在pending状态，如果数据量小还好，数据量大时，跳到新页面，旧的请求依旧没有停止，这将会十分损耗性能，这时我们应该先取消掉之前还没有获得相应的请求，再跳转页面。这里axios给我们提供了一个方法：

cancelToken其实就是用来取消ajax请求
 */
const CancelToken =axios.CancelToken

export { baseUrl };
// 添加请求拦截器
axios.interceptors.request.use(
    function (config:AxiosRequestConfig):any{
        //在发送请求前做的操作， 传token添加到请求头
        let token:any = getLocalStorage(StorageEnum.GB_TOKEN_STORE);
        if(token){
            //忽略未定义或无法赋值的语法报错
            // @ts-ignore
            config.headers.common[RequestEnum.GB_TOKEN_KEY] = token
        }
        // @ts-ignore
        config.headers["Content-Type"] = "application/json;charset=utf-8";

        return config;
    },
    function (error:any){
        //请求错误做的操作
        console.log(error);
        return Promise.reject(error)
    }
)

export type Params = { [key: string]: string | number };
export type FileConfig ={
    setCancel?:Function;
    onProgress?:Function;
    [key:string]:any
}

/**
 * @响应拦截
 */
axios.interceptors.response.use(
    (response:AxiosResponse)=>{
        if(response.status !==200){
            return Promise.reject(response)
        }
        /**
         * @code 登录过期 token验证失败 根据后端调取
         * 
         */
        if(response.data.code == UtilVar.code){
            return Promise.resolve(response)
        }
        return Promise.resolve(response)
    },
    (error:any)=>{
        console.log('error==>',error);
        let err ={
            success:false,
            msg:'未知异常，请联系管理员！',
            code: 400,
        }
        if(JSON.stringify(error).indexOf("Network Error") != -1){
            err.msg = "网络错误或服务错误！"
        }
        if(error.message == "canceled"){
            err.msg = "取消请求"
            err.code = 488
        }
        return Promise.reject(err)
    }
)

/**
 * 判断是否是加密参数，是的话进行处理
 */
let isEncryptionParam = (param:Params)=>{
    return param
}
/**
 * @description get请求方法
 * @param url 请求地址
 * @param params 请求参数
 * @returns 
 */
export const GET =async (url:string,params:Params):Promise<any> =>{
    try{
        params = isEncryptionParam(params)
        const data = await axios.get(`${baseUrl}${url}`,{
            params:params
        })
        return data.data;
    } catch(error:any){
        return Promise.reject(error)
    }
}

/**
 * @description post请求方法
 * @param url 请求地址
 * @param params 请求参数
 * @returns 
 */
export const POST =async (url:string,params:Params):Promise<any> =>{
    try{
        params = isEncryptionParam(params)
        const data = await axios.post(`${baseUrl}${url}`,params)
        return data.data
    } catch(error:any){
        return Promise.reject(error)
    }
}
/**
 * put 请求
 * @param url 请求地址
 * @param params 请求参数
 * @returns 
 */
export const PUT = async (url: string, params: Params) => {
    try {
      params = isEncryptionParam(params);
      const data = await axios.put(`${baseUrl}${url}`, params);
      return data.data;
    } catch (error) {
      return Promise.reject(error);
    }
  };
/**
 * delet 请求
 * @param url 请求地址
 * @param params 请求参数
 * @returns 
 */
  export const DELETE = async (url: string, params: Params) => {
    // console.log(params)
    try {
      params = isEncryptionParam(params);
      const data = await axios.delete(`${baseUrl}${url}`, { data: params });
      return data.data;
    } catch (error) {
      return Promise.reject(error);
    }
  };

/**
 * @description: 没有基地址 访问根目录下文件
 * @param url 请求地址
 * @param params 请求参数
 * @returns 
 */
export const GETNOBASE = async (url:string,params?:Params):Promise<any> =>{
    try{
        const data = await axios.get(url,{
            params:params
        })
        return data.data
    } catch(error:any){
        return Promise.reject(error)
    }
}

// 定义文件类型提交方法
interface fileConfigs{
    [headers:string]:{
        "Content-Type":string
    }
}

let configs:fileConfigs ={
    headers:{"Content-Type": "multipart/form-data"}
}

/**
 * @description: @文件类型提交方法
 * @param url 上传地址
 * @param params 上传参数
 * @param config 
 * @returns 
 */
export const FILEPOST =async (url:string,params:Params,config:FileConfig={}):Promise<any>=>{
    try{
        const data = await axios.post(`${baseUrl}${url}`,params,{
            ...configs,
            cancelToken:new CancelToken(function executor(c:any){
                config.setCancel && config.setCancel(c);
            }),
            //上传进度
            onUploadProgress:(e:any)=>{
                if(e.total > 0){
                    e.percent = (e.loaded / e.total) * 100;
                }
                config.onProgress && config.onProgress(e)
            },
        });
        return data;
    }catch(err){
        return Promise.reject(err)
    }
}

/**
 * 下载文档流
 * @param config 下载文件流根据后端 配置   arraybuffer || blod
 * @returns 
 */
export const FILE = async (config:FileConfig ={}) =>{
    try{
        const data = await axios({
            method:config.method || 'get',
            url: `${baseUrl}${config.url}`,
            data:config.body || {},
            params: config.param || {},
            responseType:config.responseType || 'blod',
            onDownloadProgress:(e:any)=>{
                config.onProgress && config.onProgress(e)
            }
        })
        return data
    }catch (err){
        return Promise.reject(err)
    }
}

